#ifndef __CUHB_JMAT_H__
#define __CUHB_JMAT_H__

// single J link = 12 floats
typedef struct {
    float j00, j01, j02;
    float j10, j11, j12;
    float j20, j21, j22;
} jmat;

struct Jmat {
    Config m_cfg;

    size_t m_volume;
    size_t m_pad;
    size_t m_stride;

    size_t m_strided_len;
    size_t m_tex_len;

    void*  m_cpu_buf;
    size_t m_cpu_bytes;

    void*  m_gpu_buf;
    size_t m_gpu_bytes;

    Jmat(Config &conf, int pad);
    ~Jmat();
    void cpu_to_gpu();
    void gpu_to_cpu();
    void init_ident();
    void init_gaussian(rng_uniform &rng);

    jmat at(int ix, int iy, int iz, int dir) const {
        //const int lx = m_cfg.lat[DIR_X];
        const int ly = m_cfg.lat[DIR_Y];
        const int lz = m_cfg.lat[DIR_Z];
        float4* vec = (float4*)m_cpu_buf;
        int idx = (iz) + (iy)*lz + (ix)*(lz*ly);
        float4 f1 = vec[idx + ((dir*2+0)*m_stride)];
        float4 f2 = vec[idx + ((dir*2+1)*m_stride)];
        jmat ret = { 
            f1.x, f1.y, f1.z,
            f1.y, f2.x, f2.y,
            f1.z, f2.y, f2.z
        };
        return ret;
    }
    jmat operator()(int ix, int iy, int iz, int dir) const {
        return at(ix,iy,iz,dir);
    }
};

/*
 * Local variables:
 *  mode: c++
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 *  indent-tabs-mode: nil
 * End:
 */

#endif // __CUHB_JMAT_H__
